//
//  KeyedCodingContainer.swift
//  MoonKit
//
//  Created by moon on 2019/3/5.
//  Copyright © 2019 moon. All rights reserved.
//

import Foundation

public protocol KeyedCodingContainerProtocol {
	associatedtype Key : CodingKey
	var codingOperation:CodingOperation { get }
	var codingPath: [CodingKey] { get }
	var allKeys: [Self.Key] { get }
	func contains(_ key: Self.Key) -> Bool
	
	/// 返回指定key对应的keyed容器
	///
	/// - Parameters:
	///   - type: Key类型
	///   - key: key值
	/// - Returns: 嵌套的keyed容器
	/// - Throws: `CodingError.keyNotFound` : key不存在
	/// - Throws: `CodingError.typeMismatch` : key对应的类型不为keyed容器
	mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Self.Key) throws -> KeyedCodingContainer<NestedKey> where NestedKey : CodingKey
	
	/// 返回指定key对应的unkeyed容器
	///
	/// - Parameter key: key值
	/// - Returns: 嵌套的unkeyed容器
	/// - Throws: `CodingError.keyNotFound` : key不存在
	/// - Throws: `CodingError.typeMismatch` : key对应的类型不为keyed容器
	mutating func nestedUnkeyedContainer(forKey key: Self.Key) throws -> UnkeyedCodingContainer
	
	/// 等效于调用return try superCoder(forKey: Key(stringValue: "super")!)
	///
	/// - Returns: 嵌套的编解码器
	/// - Throws: `CodingError.keyNotFound` : 解码时,key不存在
	mutating func superCoder() throws -> Coder
	
	/// 使用指定key对应的对象,构造一个Coder出来.编码时,Coder的内容将保存为key对应的值.解码时,Coder的内容为key对应的值
	///
	/// - Parameter key: key值
	/// - Returns: 嵌套的编解码器
	/// - Throws: `CodingError.keyNotFound` : 解码时,key不存在
	mutating func superCoder(forKey key: Self.Key) throws -> Coder
	
	/// 编码nil到指定的key中
	///
	/// - parameter key: 要编码的key
	/// - throws: `CodingError.invalidValue`: 当前容器不支持编码nil
	mutating func encodeNil(forKey key: Self.Key) throws
	
	/// 编码对象到指定的key中
	///
	/// - parameter value: 要编码的对象
	/// - parameter key: 要编码的key
	mutating func encode<T>(_ value: T, forKey key: Self.Key) throws where T : Codable
	
	/// 如果value不等于nil时,编码对象到指定的key中.value=nil时,不操作
	///
	/// - parameter value: 要编码的对象
	/// - parameter key: 要编码的key
	mutating func encodeIfPresent<T>(_ value: T?, forKey key: Self.Key) throws where T : Codable
	
	mutating func encode(_ value: Bool, forKey key: Self.Key) throws
	mutating func encodeIfPresent(_ value: Bool?, forKey key: Self.Key) throws
	
	mutating func encode(_ value: String, forKey key: Self.Key) throws
	mutating func encodeIfPresent(_ value: String?, forKey key: Self.Key) throws
	
	mutating func encode(_ value: Double, forKey key: Self.Key) throws
	mutating func encodeIfPresent(_ value: Double?, forKey key: Self.Key) throws
	
	mutating func encode(_ value: Float, forKey key: Self.Key) throws
	mutating func encodeIfPresent(_ value: Float?, forKey key: Self.Key) throws
	
	mutating func encode(_ value: Int, forKey key: Self.Key) throws
	mutating func encodeIfPresent(_ value: Int?, forKey key: Self.Key) throws
	
	mutating func encode(_ value: Int8, forKey key: Self.Key) throws
	mutating func encodeIfPresent(_ value: Int8?, forKey key: Self.Key) throws
	
	mutating func encode(_ value: Int16, forKey key: Self.Key) throws
	mutating func encodeIfPresent(_ value: Int16?, forKey key: Self.Key) throws
	
	mutating func encode(_ value: Int32, forKey key: Self.Key) throws
	mutating func encodeIfPresent(_ value: Int32?, forKey key: Self.Key) throws
	
	mutating func encode(_ value: Int64, forKey key: Self.Key) throws
	mutating func encodeIfPresent(_ value: Int64?, forKey key: Self.Key) throws
	
	mutating func encode(_ value: UInt, forKey key: Self.Key) throws
	mutating func encodeIfPresent(_ value: UInt?, forKey key: Self.Key) throws
	
	mutating func encode(_ value: UInt8, forKey key: Self.Key) throws
	mutating func encodeIfPresent(_ value: UInt8?, forKey key: Self.Key) throws
	
	mutating func encode(_ value: UInt16, forKey key: Self.Key) throws
	mutating func encodeIfPresent(_ value: UInt16?, forKey key: Self.Key) throws
	
	mutating func encode(_ value: UInt32, forKey key: Self.Key) throws
	mutating func encodeIfPresent(_ value: UInt32?, forKey key: Self.Key) throws
	
	mutating func encode(_ value: UInt64, forKey key: Self.Key) throws
	mutating func encodeIfPresent(_ value: UInt64?, forKey key: Self.Key) throws
	
	/// 从指定的key中解码出nil来
	///
	/// - parameter key: 要解码的key
	/// - returns: key对应的值是否为null
	/// - throws: `CodingError.keyNotFound` : key不存在
	mutating func decodeNil(forKey key: Self.Key) throws -> Bool

	/// 从指定的key中解码出对象来
	///
	/// - parameter type: 对象类型
	/// - parameter key: 要解码的key
	/// - returns: 解码出来的对象
	/// - throws: `DecodingError.typeMismatch`: key对应的值,与指定类型不符合
	/// - throws: `CodingError.keyNotFound` : key不存在
	/// - throws: `CodingError.valueNotFound` : key对应的值为null
	mutating func decode<T>(_ type: T.Type, forKey key: Self.Key) throws -> T where T : Codable
	
	/// 从指定的key中解码出对象来,如果key不存在或者key对应的值为null时,解码出nil
	///
	/// - parameter type: 对象类型
	/// - parameter key: 要解码的key
	/// - returns: 解码出来的对象或nil(key对应的值为null时),或者key不存在
	/// - throws: `DecodingError.typeMismatch`: key对应的值,与指定类型不符合
	mutating func decodeIfPresent<T>(_ type: T.Type, forKey key: Self.Key) throws -> T? where T : Codable
	
	mutating func decode(_ type: Bool.Type, forKey key: Self.Key) throws -> Bool
	mutating func decodeIfPresent(_ type: Bool.Type, forKey key: Self.Key) throws -> Bool?
	
	mutating func decode(_ type: String.Type, forKey key: Self.Key) throws -> String
	mutating func decodeIfPresent(_ type: String.Type, forKey key: Self.Key) throws -> String?
	
	mutating func decode(_ type: Double.Type, forKey key: Self.Key) throws -> Double
	mutating func decodeIfPresent(_ type: Double.Type, forKey key: Self.Key) throws -> Double?
	
	mutating func decode(_ type: Float.Type, forKey key: Self.Key) throws -> Float
	mutating func decodeIfPresent(_ type: Float.Type, forKey key: Self.Key) throws -> Float?
	
	mutating func decode(_ type: Int.Type, forKey key: Self.Key) throws -> Int
	mutating func decodeIfPresent(_ type: Int.Type, forKey key: Self.Key) throws -> Int?
	
	mutating func decode(_ type: Int8.Type, forKey key: Self.Key) throws -> Int8
	mutating func decodeIfPresent(_ type: Int8.Type, forKey key: Self.Key) throws -> Int8?
	
	mutating func decode(_ type: Int16.Type, forKey key: Self.Key) throws -> Int16
	mutating func decodeIfPresent(_ type: Int16.Type, forKey key: Self.Key) throws -> Int16?
	
	mutating func decode(_ type: Int32.Type, forKey key: Self.Key) throws -> Int32
	mutating func decodeIfPresent(_ type: Int32.Type, forKey key: Self.Key) throws -> Int32?
	
	mutating func decode(_ type: Int64.Type, forKey key: Self.Key) throws -> Int64
	mutating func decodeIfPresent(_ type: Int64.Type, forKey key: Self.Key) throws -> Int64?
	
	mutating func decode(_ type: UInt.Type, forKey key: Self.Key) throws -> UInt
	mutating func decodeIfPresent(_ type: UInt.Type, forKey key: Self.Key) throws -> UInt?
	
	mutating func decode(_ type: UInt8.Type, forKey key: Self.Key) throws -> UInt8
	mutating func decodeIfPresent(_ type: UInt8.Type, forKey key: Self.Key) throws -> UInt8?
	
	mutating func decode(_ type: UInt16.Type, forKey key: Self.Key) throws -> UInt16
	mutating func decodeIfPresent(_ type: UInt16.Type, forKey key: Self.Key) throws -> UInt16?
	
	mutating func decode(_ type: UInt32.Type, forKey key: Self.Key) throws -> UInt32
	mutating func decodeIfPresent(_ type: UInt32.Type, forKey key: Self.Key) throws -> UInt32?
	
	mutating func decode(_ type: UInt64.Type, forKey key: Self.Key) throws -> UInt64
	mutating func decodeIfPresent(_ type: UInt64.Type, forKey key: Self.Key) throws -> UInt64?

}

public struct KeyedCodingContainer<K> : KeyedCodingContainerProtocol where K : CodingKey {
	public typealias Key = K
	
	/// The container for the concrete decoder. The type is _*Base so that it's
	/// generic on the key type.
//	@usableFromInline
	internal var _box: _KeyedCodingContainerBase<Key>

	public init<Container : KeyedCodingContainerProtocol>(
		_ container: Container) where Container.Key == Key {
		_box = _KeyedCodingContainerBox(container)
	}
	public var codingOperation:CodingOperation {
		return _box.codingOperation
	}
	public var codingPath: [CodingKey] {
		return _box.codingPath
	}
	public var allKeys: [Key] {
		return _box.allKeys
	}
	public func contains(_ key: Key) -> Bool {
		return _box.contains(key)
	}
	
	public mutating func decodeNil(forKey key: Key) throws -> Bool {
		return try _box.decodeNil(forKey: key)
	}
	
	public mutating func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
		return try _box.decode(type, forKey: key)
	}
	public mutating func decodeIfPresent(_ type: Bool.Type, forKey key: Key) throws -> Bool? {
		return try _box.decodeIfPresent(type, forKey: key)
	}
	
	public mutating func decode(_ type: String.Type, forKey key: Key) throws -> String {
		return try _box.decode(type, forKey: key)
	}
	public mutating func decodeIfPresent(_ type: String.Type, forKey key: Key) throws -> String? {
		return try _box.decodeIfPresent(type, forKey: key)
	}
	
	public mutating func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
		return try _box.decode(type, forKey: key)
	}
	public mutating func decodeIfPresent(_ type: Double.Type, forKey key: Key) throws -> Double? {
		return try _box.decodeIfPresent(type, forKey: key)
	}
	
	public mutating func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
		return try _box.decode(type, forKey: key)
	}
	public mutating func decodeIfPresent(_ type: Float.Type, forKey key: Key) throws -> Float? {
		return try _box.decodeIfPresent(type, forKey: key)
	}
	
	public mutating func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
		return try _box.decode(type, forKey: key)
	}
	public mutating func decodeIfPresent(_ type: Int.Type, forKey key: Key) throws -> Int? {
		return try _box.decodeIfPresent(type, forKey: key)
	}
	
	public mutating func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
		return try _box.decode(type, forKey: key)
	}
	public mutating func decodeIfPresent(_ type: Int8.Type, forKey key: Key) throws -> Int8? {
		return try _box.decodeIfPresent(type, forKey: key)
	}
	
	public mutating func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
		return try _box.decode(type, forKey: key)
	}
	public mutating func decodeIfPresent(_ type: Int16.Type, forKey key: Key) throws -> Int16? {
		return try _box.decodeIfPresent(type, forKey: key)
	}
	
	public mutating func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
		return try _box.decode(type, forKey: key)
	}
	public mutating func decodeIfPresent(_ type: Int32.Type, forKey key: Key) throws -> Int32? {
		return try _box.decodeIfPresent(type, forKey: key)
	}
	
	public mutating func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
		return try _box.decode(type, forKey: key)
	}
	public mutating func decodeIfPresent(_ type: Int64.Type, forKey key: Key) throws -> Int64? {
		return try _box.decodeIfPresent(type, forKey: key)
	}
	
	public mutating func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
		return try _box.decode(type, forKey: key)
	}
	public mutating func decodeIfPresent(_ type: UInt.Type, forKey key: Key) throws -> UInt? {
		return try _box.decodeIfPresent(type, forKey: key)
	}
	
	public mutating func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
		return try _box.decode(type, forKey: key)
	}
	public mutating func decodeIfPresent(_ type: UInt8.Type, forKey key: Key) throws -> UInt8? {
		return try _box.decodeIfPresent(type, forKey: key)
	}
	
	public mutating func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
		return try _box.decode(type, forKey: key)
	}
	public mutating func decodeIfPresent(_ type: UInt16.Type, forKey key: Key) throws -> UInt16? {
		return try _box.decodeIfPresent(type, forKey: key)
	}
	
	public mutating func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
		return try _box.decode(type, forKey: key)
	}
	public mutating func decodeIfPresent(_ type: UInt32.Type, forKey key: Key) throws -> UInt32? {
		return try _box.decodeIfPresent(type, forKey: key)
	}
	
	public mutating func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
		return try _box.decode(type, forKey: key)
	}
	public mutating func decodeIfPresent(_ type: UInt64.Type, forKey key: Key) throws -> UInt64? {
		return try _box.decodeIfPresent(type, forKey: key)
	}

	
	public mutating func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T : Codable {
		return try _box.decode(type, forKey: key)
	}
	public mutating func decodeIfPresent<T>(_ type: T.Type, forKey key: Key) throws -> T? where T : Codable {
		return try _box.decodeIfPresent(type, forKey: key)
	}
	
	public mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedCodingContainer<NestedKey> where NestedKey : CodingKey {
		return try _box.nestedContainer(keyedBy: type, forKey: key)
	}
	public mutating func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedCodingContainer {
		return try _box.nestedUnkeyedContainer(forKey: key)
	}
	
	public mutating func encodeNil(forKey key: Key) throws {
		try _box.encodeNil(forKey: key)
	}
	
	public mutating func encode(_ value: Bool, forKey key: Key) throws {
		try _box.encode(value, forKey: key)
	}
	public mutating func encodeIfPresent(_ value: Bool?, forKey key: Key) throws {
		try _box.encodeIfPresent(value, forKey: key)
	}
	
	public mutating func encode(_ value: String, forKey key: Key) throws {
		try _box.encode(value, forKey: key)
	}
	public mutating func encodeIfPresent(_ value: String?, forKey key: Key) throws {
		try _box.encodeIfPresent(value, forKey: key)
	}
	
	public mutating func encode(_ value: Double, forKey key: Key) throws {
		try _box.encode(value, forKey: key)
	}
	public mutating func encodeIfPresent(_ value: Double?, forKey key: Key) throws {
		try _box.encodeIfPresent(value, forKey: key)
	}
	
	public mutating func encode(_ value: Float, forKey key: Key) throws {
		try _box.encode(value, forKey: key)
	}
	public mutating func encodeIfPresent(_ value: Float?, forKey key: Key) throws {
		try _box.encodeIfPresent(value, forKey: key)
	}
	
	public mutating func encode(_ value: Int, forKey key: Key) throws {
		try _box.encode(value, forKey: key)
	}
	public mutating func encodeIfPresent(_ value: Int?, forKey key: Key) throws {
		try _box.encodeIfPresent(value, forKey: key)
	}
	
	public mutating func encode(_ value: Int8, forKey key: Key) throws {
		try _box.encode(value, forKey: key)
	}
	public mutating func encodeIfPresent(_ value: Int8?, forKey key: Key) throws {
		try _box.encodeIfPresent(value, forKey: key)
	}
	
	public mutating func encode(_ value: Int16, forKey key: Key) throws {
		try _box.encode(value, forKey: key)
	}
	public mutating func encodeIfPresent(_ value: Int16?, forKey key: Key) throws {
		try _box.encodeIfPresent(value, forKey: key)
	}
	
	public mutating func encode(_ value: Int32, forKey key: Key) throws {
		try _box.encode(value, forKey: key)
	}
	public mutating func encodeIfPresent(_ value: Int32?, forKey key: Key) throws {
		try _box.encodeIfPresent(value, forKey: key)
	}
	
	public mutating func encode(_ value: Int64, forKey key: Key) throws {
		try _box.encode(value, forKey: key)
	}
	public mutating func encodeIfPresent(_ value: Int64?, forKey key: Key) throws {
		try _box.encodeIfPresent(value, forKey: key)
	}
	
	public mutating func encode(_ value: UInt, forKey key: Key) throws {
		try _box.encode(value, forKey: key)
	}
	public mutating func encodeIfPresent(_ value: UInt?, forKey key: Key) throws {
		try _box.encodeIfPresent(value, forKey: key)
	}
	
	public mutating func encode(_ value: UInt8, forKey key: Key) throws {
		try _box.encode(value, forKey: key)
	}
	public mutating func encodeIfPresent(_ value: UInt8?, forKey key: Key) throws {
		try _box.encodeIfPresent(value, forKey: key)
	}
	
	public mutating func encode(_ value: UInt16, forKey key: Key) throws {
		try _box.encode(value, forKey: key)
	}
	public mutating func encodeIfPresent(_ value: UInt16?, forKey key: Key) throws {
		try _box.encodeIfPresent(value, forKey: key)
	}
	
	public mutating func encode(_ value: UInt32, forKey key: Key) throws {
		try _box.encode(value, forKey: key)
	}
	public mutating func encodeIfPresent(_ value: UInt32?, forKey key: Key) throws {
		try _box.encodeIfPresent(value, forKey: key)
	}
	
	public mutating func encode(_ value: UInt64, forKey key: Key) throws {
		try _box.encode(value, forKey: key)
	}
	public mutating func encodeIfPresent(_ value: UInt64?, forKey key: Key) throws {
		try _box.encodeIfPresent(value, forKey: key)
	}
	
	public mutating func encode<T>(_ value: T, forKey key: Key) throws where T : Codable {
		try _box.encode(value, forKey: key)
	}
	public mutating func encodeIfPresent<T>(_ value: T?, forKey key: Key) throws where T : Codable {
		try _box.encodeIfPresent(value, forKey: key)
	}
	public mutating func superCoder() throws -> Coder {
		return try _box.superCoder()
	}
	public mutating func superCoder(forKey key: Key) throws -> Coder {
		return try _box.superCoder(forKey: key)
	}
}

internal class _KeyedCodingContainerBase<Key : CodingKey> {
	@inlinable
	init(){}
	
	@inlinable
	deinit {}
	
	@inlinable
	var codingOperation: CodingOperation {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	var codingPath: [CodingKey] {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	var allKeys: [Key] {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func contains(_ key: Key) -> Bool {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decodeNil(forKey key: Key) throws -> Bool {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decodeIfPresent(_ type: Bool.Type, forKey key: Key) throws -> Bool? {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decode(_ type: String.Type, forKey key: Key) throws -> String {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decodeIfPresent(_ type: String.Type, forKey key: Key) throws -> String? {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decodeIfPresent(_ type: Double.Type, forKey key: Key) throws -> Double? {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decodeIfPresent(_ type: Float.Type, forKey key: Key) throws -> Float? {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decodeIfPresent(_ type: Int.Type, forKey key: Key) throws -> Int? {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decodeIfPresent(_ type: Int8.Type, forKey key: Key) throws -> Int8? {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decodeIfPresent(_ type: Int16.Type, forKey key: Key) throws -> Int16? {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decodeIfPresent(_ type: Int32.Type, forKey key: Key) throws -> Int32? {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decodeIfPresent(_ type: Int64.Type, forKey key: Key) throws -> Int64? {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decodeIfPresent(_ type: UInt.Type, forKey key: Key) throws -> UInt? {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decodeIfPresent(_ type: UInt8.Type, forKey key: Key) throws -> UInt8? {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decodeIfPresent(_ type: UInt16.Type, forKey key: Key) throws -> UInt16? {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decodeIfPresent(_ type: UInt32.Type, forKey key: Key) throws -> UInt32? {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decodeIfPresent(_ type: UInt64.Type, forKey key: Key) throws -> UInt64? {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}

	@inlinable
	func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T : Codable {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func decodeIfPresent<T>(_ type: T.Type, forKey key: Key) throws -> T? where T : Codable {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedCodingContainer<NestedKey> where NestedKey : CodingKey {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedCodingContainer {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encodeNil(forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encode(_ value: Bool, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encodeIfPresent(_ value: Bool?, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encode(_ value: String, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encodeIfPresent(_ value: String?, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encode(_ value: Double, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encodeIfPresent(_ value: Double?, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encode(_ value: Float, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encodeIfPresent(_ value: Float?, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encode(_ value: Int, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encodeIfPresent(_ value: Int?, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encode(_ value: Int8, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encodeIfPresent(_ value: Int8?, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encode(_ value: Int16, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encodeIfPresent(_ value: Int16?, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encode(_ value: Int32, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encodeIfPresent(_ value: Int32?, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encode(_ value: Int64, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encodeIfPresent(_ value: Int64?, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encode(_ value: UInt, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encodeIfPresent(_ value: UInt?, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encode(_ value: UInt8, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encodeIfPresent(_ value: UInt8?, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encode(_ value: UInt16, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encodeIfPresent(_ value: UInt16?, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encode(_ value: UInt32, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encodeIfPresent(_ value: UInt32?, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encode(_ value: UInt64, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encodeIfPresent(_ value: UInt64?, forKey key: Key) throws {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}

	@inlinable
	func encode<T>(_ value: T, forKey key: Key) throws where T : Codable {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func encodeIfPresent<T>(_ value: T?, forKey key: Key) throws where T : Codable {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func superCoder() throws -> Coder {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
	@inlinable
	func superCoder(forKey key: Key) throws -> Coder {
		fatalError("_KeyedCodingContainerBase cannot be used directly.")
	}
}

//@usableFromInline
final class _KeyedCodingContainerBox<Concrete:KeyedCodingContainerProtocol> : _KeyedCodingContainerBase<Concrete.Key> {
	@usableFromInline
	typealias Key = Concrete.Key
	
	@usableFromInline
	internal var concrete: Concrete
	
	internal init(_ container: Concrete) {
		concrete = container
	}
	@inlinable
	override var codingOperation: CodingOperation {
		return concrete.codingOperation
	}
	@inlinable
	override var codingPath: [CodingKey] {
		return concrete.codingPath
	}
	@inlinable
	override var allKeys: [Key] {
		return concrete.allKeys
	}
	@inlinable
	override func contains(_ key: Key) -> Bool {
		return concrete.contains(key)
	}
	@inlinable
	override func decodeNil(forKey key: Key) throws -> Bool {
		return try concrete.decodeNil(forKey: key)
	}
	@inlinable
	override func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
		return try concrete.decode(type, forKey: key)
	}
	@inlinable
	override func decodeIfPresent(_ type: Bool.Type, forKey key: Key) throws -> Bool? {
		return try concrete.decodeIfPresent(type, forKey: key)
	}
	@inlinable
	override func decode(_ type: String.Type, forKey key: Key) throws -> String {
		return try concrete.decode(type, forKey: key)
	}
	@inlinable
	override func decodeIfPresent(_ type: String.Type, forKey key: Key) throws -> String? {
		return try concrete.decodeIfPresent(type, forKey: key)
	}
	@inlinable
	override func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
		return try concrete.decode(type, forKey: key)
	}
	@inlinable
	override func decodeIfPresent(_ type: Double.Type, forKey key: Key) throws -> Double? {
		return try concrete.decodeIfPresent(type, forKey: key)
	}
	@inlinable
	override func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
		return try concrete.decode(type, forKey: key)
	}
	@inlinable
	override func decodeIfPresent(_ type: Float.Type, forKey key: Key) throws -> Float? {
		return try concrete.decodeIfPresent(type, forKey: key)
	}
	@inlinable
	override func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
		return try concrete.decode(type, forKey: key)
	}
	@inlinable
	override func decodeIfPresent(_ type: Int.Type, forKey key: Key) throws -> Int? {
		return try concrete.decodeIfPresent(type, forKey: key)
	}
	@inlinable
	override func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
		return try concrete.decode(type, forKey: key)
	}
	@inlinable
	override func decodeIfPresent(_ type: Int8.Type, forKey key: Key) throws -> Int8? {
		return try concrete.decodeIfPresent(type, forKey: key)
	}
	@inlinable
	override func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
		return try concrete.decode(type, forKey: key)
	}
	@inlinable
	override func decodeIfPresent(_ type: Int16.Type, forKey key: Key) throws -> Int16? {
		return try concrete.decodeIfPresent(type, forKey: key)
	}
	@inlinable
	override func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
		return try concrete.decode(type, forKey: key)
	}
	@inlinable
	override func decodeIfPresent(_ type: Int32.Type, forKey key: Key) throws -> Int32? {
		return try concrete.decodeIfPresent(type, forKey: key)
	}
	@inlinable
	override func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
		return try concrete.decode(type, forKey: key)
	}
	@inlinable
	override func decodeIfPresent(_ type: Int64.Type, forKey key: Key) throws -> Int64? {
		return try concrete.decodeIfPresent(type, forKey: key)
	}
	@inlinable
	override func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
		return try concrete.decode(type, forKey: key)
	}
	@inlinable
	override func decodeIfPresent(_ type: UInt.Type, forKey key: Key) throws -> UInt? {
		return try concrete.decodeIfPresent(type, forKey: key)
	}
	@inlinable
	override func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
		return try concrete.decode(type, forKey: key)
	}
	@inlinable
	override func decodeIfPresent(_ type: UInt8.Type, forKey key: Key) throws -> UInt8? {
		return try concrete.decodeIfPresent(type, forKey: key)
	}
	@inlinable
	override func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
		return try concrete.decode(type, forKey: key)
	}
	@inlinable
	override func decodeIfPresent(_ type: UInt16.Type, forKey key: Key) throws -> UInt16? {
		return try concrete.decodeIfPresent(type, forKey: key)
	}
	@inlinable
	override func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
		return try concrete.decode(type, forKey: key)
	}
	@inlinable
	override func decodeIfPresent(_ type: UInt32.Type, forKey key: Key) throws -> UInt32? {
		return try concrete.decodeIfPresent(type, forKey: key)
	}
	@inlinable
	override func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
		return try concrete.decode(type, forKey: key)
	}
	@inlinable
	override func decodeIfPresent(_ type: UInt64.Type, forKey key: Key) throws -> UInt64? {
		return try concrete.decodeIfPresent(type, forKey: key)
	}
	@inlinable
	override func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T : Codable {
		return try concrete.decode(type, forKey: key)
	}
	@inlinable
	override func decodeIfPresent<T>(_ type: T.Type, forKey key: Key) throws -> T? where T : Codable {
		return try concrete.decodeIfPresent(type, forKey: key)
	}
	@inlinable
	override func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedCodingContainer<NestedKey> where NestedKey : CodingKey {
		return try concrete.nestedContainer(keyedBy: type, forKey: key)
	}
	@inlinable
	override func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedCodingContainer {
		return try concrete.nestedUnkeyedContainer(forKey: key)
	}
	@inlinable
	override func encodeNil(forKey key: Key) throws {
		try concrete.encodeNil(forKey: key)
	}
	@inlinable
	override func encode(_ value: Bool, forKey key: Key) throws {
		try concrete.encode(value, forKey: key)
	}
	@inlinable
	override func encodeIfPresent(_ value: Bool?, forKey key: Key) throws {
		try concrete.encodeIfPresent(value, forKey: key)
	}
	@inlinable
	override func encode(_ value: String, forKey key: Key) throws {
		try concrete.encode(value, forKey: key)
	}
	@inlinable
	override func encodeIfPresent(_ value: String?, forKey key: Key) throws {
		try concrete.encodeIfPresent(value, forKey: key)
	}
	@inlinable
	override func encode(_ value: Double, forKey key: Key) throws {
		try concrete.encode(value, forKey: key)
	}
	@inlinable
	override func encodeIfPresent(_ value: Double?, forKey key: Key) throws {
		try concrete.encodeIfPresent(value, forKey: key)
	}
	@inlinable
	override func encode(_ value: Float, forKey key: Key) throws {
		try concrete.encode(value, forKey: key)
	}
	@inlinable
	override func encodeIfPresent(_ value: Float?, forKey key: Key) throws {
		try concrete.encodeIfPresent(value, forKey: key)
	}
	@inlinable
	override func encode(_ value: Int, forKey key: Key) throws {
		try concrete.encode(value, forKey: key)
	}
	@inlinable
	override func encodeIfPresent(_ value: Int?, forKey key: Key) throws {
		try concrete.encodeIfPresent(value, forKey: key)
	}
	@inlinable
	override func encode(_ value: Int8, forKey key: Key) throws {
		try concrete.encode(value, forKey: key)
	}
	@inlinable
	override func encodeIfPresent(_ value: Int8?, forKey key: Key) throws {
		try concrete.encodeIfPresent(value, forKey: key)
	}
	@inlinable
	override func encode(_ value: Int16, forKey key: Key) throws {
		try concrete.encode(value, forKey: key)
	}
	@inlinable
	override func encodeIfPresent(_ value: Int16?, forKey key: Key) throws {
		try concrete.encodeIfPresent(value, forKey: key)
	}
	@inlinable
	override func encode(_ value: Int32, forKey key: Key) throws {
		try concrete.encode(value, forKey: key)
	}
	@inlinable
	override func encodeIfPresent(_ value: Int32?, forKey key: Key) throws {
		try concrete.encodeIfPresent(value, forKey: key)
	}
	@inlinable
	override func encode(_ value: Int64, forKey key: Key) throws {
		try concrete.encode(value, forKey: key)
	}
	@inlinable
	override func encodeIfPresent(_ value: Int64?, forKey key: Key) throws {
		try concrete.encodeIfPresent(value, forKey: key)
	}
	@inlinable
	override func encode(_ value: UInt, forKey key: Key) throws {
		try concrete.encode(value, forKey: key)
	}
	@inlinable
	override func encodeIfPresent(_ value: UInt?, forKey key: Key) throws {
		try concrete.encodeIfPresent(value, forKey: key)
	}
	@inlinable
	override func encode(_ value: UInt8, forKey key: Key) throws {
		try concrete.encode(value, forKey: key)
	}
	@inlinable
	override func encodeIfPresent(_ value: UInt8?, forKey key: Key) throws {
		try concrete.encodeIfPresent(value, forKey: key)
	}
	@inlinable
	override func encode(_ value: UInt16, forKey key: Key) throws {
		try concrete.encode(value, forKey: key)
	}
	@inlinable
	override func encodeIfPresent(_ value: UInt16?, forKey key: Key) throws {
		try concrete.encodeIfPresent(value, forKey: key)
	}
	@inlinable
	override func encode(_ value: UInt32, forKey key: Key) throws {
		try concrete.encode(value, forKey: key)
	}
	@inlinable
	override func encodeIfPresent(_ value: UInt32?, forKey key: Key) throws {
		try concrete.encodeIfPresent(value, forKey: key)
	}
	@inlinable
	override func encode(_ value: UInt64, forKey key: Key) throws {
		try concrete.encode(value, forKey: key)
	}
	@inlinable
	override func encodeIfPresent(_ value: UInt64?, forKey key: Key) throws {
		try concrete.encodeIfPresent(value, forKey: key)
	}
	@inlinable
	override func encode<T>(_ value: T, forKey key: Key) throws where T : Codable {
		try concrete.encode(value, forKey: key)
	}
	@inlinable
	override func encodeIfPresent<T>(_ value: T?, forKey key: Key) throws where T : Codable {
		try concrete.encodeIfPresent(value, forKey: key)
	}
	
	@inlinable
	override func superCoder() throws -> Coder {
		return try concrete.superCoder()
	}
	@inlinable
	override func superCoder(forKey key: Key) throws -> Coder {
		return try concrete.superCoder(forKey: key)
	}
}

extension KeyedCodingContainerProtocol {
	@inlinable
	public mutating func encodeIfPresent(_ value: Bool?, forKey key: Key) throws {
		if let v = value { try encode(v, forKey: key) }
	}
	@inlinable
	public mutating func encodeIfPresent(_ value: String?, forKey key: Key) throws {
		if let v = value { try encode(v, forKey: key) }
	}
	@inlinable
	public mutating func encodeIfPresent(_ value: Double?, forKey key: Key) throws {
		if let v = value { try encode(v, forKey: key) }
	}
	@inlinable
	public mutating func encodeIfPresent(_ value: Float?, forKey key: Key) throws {
		if let v = value { try encode(v, forKey: key) }
	}
	@inlinable
	public mutating func encodeIfPresent(_ value: Int?, forKey key: Key) throws {
		if let v = value { try encode(v, forKey: key) }
	}
	@inlinable
	public mutating func encodeIfPresent(_ value: Int8?, forKey key: Key) throws {
		if let v = value { try encode(v, forKey: key) }
	}
	@inlinable
	public mutating func encodeIfPresent(_ value: Int16?, forKey key: Key) throws {
		if let v = value { try encode(v, forKey: key) }
	}
	@inlinable
	public mutating func encodeIfPresent(_ value: Int32?, forKey key: Key) throws {
		if let v = value { try encode(v, forKey: key) }
	}
	@inlinable
	public mutating func encodeIfPresent(_ value: Int64?, forKey key: Key) throws {
		if let v = value { try encode(v, forKey: key) }
	}
	@inlinable
	public mutating func encodeIfPresent(_ value: UInt?, forKey key: Key) throws {
		if let v = value { try encode(v, forKey: key) }
	}
	@inlinable
	public mutating func encodeIfPresent(_ value: UInt8?, forKey key: Key) throws {
		if let v = value { try encode(v, forKey: key) }
	}
	@inlinable
	public mutating func encodeIfPresent(_ value: UInt16?, forKey key: Key) throws {
		if let v = value { try encode(v, forKey: key) }
	}
	@inlinable
	public mutating func encodeIfPresent(_ value: UInt32?, forKey key: Key) throws {
		if let v = value { try encode(v, forKey: key) }
	}
	@inlinable
	public mutating func encodeIfPresent(_ value: UInt64?, forKey key: Key) throws {
		if let v = value { try encode(v, forKey: key) }
	}
	@inlinable // FIXME(sil-serialize-all)
	public mutating func encodeIfPresent<T : Codable>(_ value: T?, forKey key: Key) throws {
		if let v = value { try encode(v, forKey: key) }
	}
}

extension KeyedCodingContainerProtocol {
	@inlinable
	public mutating func decodeIfPresent(_ type: Bool.Type, forKey key: Key) throws -> Bool? {
		return try !self.contains(key) || self.decodeNil(forKey: key) ? nil : try self.decode(type, forKey: key)
	}
	@inlinable
	public mutating func decodeIfPresent(_ type: String.Type, forKey key: Key) throws -> String? {
		return try !self.contains(key) || self.decodeNil(forKey: key) ? nil : try self.decode(type, forKey: key)
	}
	@inlinable
	public mutating func decodeIfPresent(_ type: Double.Type, forKey key: Key) throws -> Double? {
		return try !self.contains(key) || self.decodeNil(forKey: key) ? nil : try self.decode(type, forKey: key)
	}
	@inlinable
	public mutating func decodeIfPresent(_ type: Float.Type, forKey key: Key) throws -> Float? {
		return try !self.contains(key) || self.decodeNil(forKey: key) ? nil : try self.decode(type, forKey: key)
	}
	@inlinable
	public mutating func decodeIfPresent(_ type: Int.Type, forKey key: Key) throws -> Int? {
		return try !self.contains(key) || self.decodeNil(forKey: key) ? nil : try self.decode(type, forKey: key)
	}
	@inlinable
	public mutating func decodeIfPresent(_ type: Int8.Type, forKey key: Key) throws -> Int8? {
		return try !self.contains(key) || self.decodeNil(forKey: key) ? nil : try self.decode(type, forKey: key)
	}
	@inlinable
	public mutating func decodeIfPresent(_ type: Int16.Type, forKey key: Key) throws -> Int16? {
		return try !self.contains(key) || self.decodeNil(forKey: key) ? nil : try self.decode(type, forKey: key)
	}
	@inlinable
	public mutating func decodeIfPresent(_ type: Int32.Type, forKey key: Key) throws -> Int32? {
		return try !self.contains(key) || self.decodeNil(forKey: key) ? nil : try self.decode(type, forKey: key)
	}
	@inlinable
	public mutating func decodeIfPresent(_ type: Int64.Type, forKey key: Key) throws -> Int64? {
		return try !self.contains(key) || self.decodeNil(forKey: key) ? nil : try self.decode(type, forKey: key)
	}
	@inlinable
	public mutating func decodeIfPresent(_ type: UInt.Type, forKey key: Key) throws -> UInt? {
		return try !self.contains(key) || self.decodeNil(forKey: key) ? nil : try self.decode(type, forKey: key)
	}
	@inlinable
	public mutating func decodeIfPresent(_ type: UInt8.Type, forKey key: Key) throws -> UInt8? {
		return try !self.contains(key) || self.decodeNil(forKey: key) ? nil : try self.decode(type, forKey: key)
	}
	@inlinable
	public mutating func decodeIfPresent(_ type: UInt16.Type, forKey key: Key) throws -> UInt16? {
		return try !self.contains(key) || self.decodeNil(forKey: key) ? nil : try self.decode(type, forKey: key)
	}
	@inlinable
	public mutating func decodeIfPresent(_ type: UInt32.Type, forKey key: Key) throws -> UInt32? {
		return try !self.contains(key) || self.decodeNil(forKey: key) ? nil : try self.decode(type, forKey: key)
	}
	@inlinable
	public mutating func decodeIfPresent(_ type: UInt64.Type, forKey key: Key) throws -> UInt64? {
		return try !self.contains(key) || self.decodeNil(forKey: key) ? nil : try self.decode(type, forKey: key)
	}
	@inlinable
	public mutating func decodeIfPresent<T>(_ type: T.Type, forKey key: Key) throws -> T? where T : Codable {
		return try !self.contains(key) || self.decodeNil(forKey: key) ? nil : try self.decode(type, forKey: key)
	}
}

extension KeyedCodingContainerProtocol {
	/// 编码指定类型的对象到指定的key中
	/// 如果T为以下类型:['Bool', 'String', 'Double', 'Float','Int', 'Int8', 'Int16', 'Int32', 'Int64','UInt', 'UInt8', 'UInt16', 'UInt32', 'UInt64'],则会调用具体类型对应的方法,否则调用泛型的T方法
	///
	/// - parameter value: 要编码的对象
	/// - parameter key: 要编码的key
	public mutating func encodeCodableValue<T>(_ value: T, forKey key: Self.Key) throws where T : Codable {
		switch value {
		case let v as Bool:
			try encode(v, forKey: key)
		case let v as String:
			try encode(v, forKey: key)
		case let v as Double:
			try encode(v, forKey: key)
		case let v as Float:
			try encode(v, forKey: key)
		case let v as Int:
			try encode(v, forKey: key)
		case let v as Int8:
			try encode(v, forKey: key)
		case let v as Int16:
			try encode(v, forKey: key)
		case let v as Int32:
			try encode(v, forKey: key)
		case let v as Int64:
			try encode(v, forKey: key)
		case let v as UInt:
			try encode(v, forKey: key)
		case let v as UInt8:
			try encode(v, forKey: key)
		case let v as UInt16:
			try encode(v, forKey: key)
		case let v as UInt32:
			try encode(v, forKey: key)
		case let v as UInt64:
			try encode(v, forKey: key)
		default:
			try encode(value, forKey: key)
		}
	}
	
	/// 如果value不等于nil时,编码对象到指定的key中.value=nil时,不操作
	/// 如果T为以下类型:['Bool', 'String', 'Double', 'Float','Int', 'Int8', 'Int16', 'Int32', 'Int64','UInt', 'UInt8', 'UInt16', 'UInt32', 'UInt64'],则会调用具体类型对应的方法,否则调用泛型的T方法
	///
	/// - parameter value: 要编码的对象
	/// - parameter key: 要编码的key
	public mutating func encodeCodableValueIfPresent<T>(_ value: T?, forKey key: Self.Key) throws where T : Codable {
		switch value {
		case let v as Bool:
			try encodeIfPresent(v, forKey: key)
		case let v as String:
			try encodeIfPresent(v, forKey: key)
		case let v as Double:
			try encodeIfPresent(v, forKey: key)
		case let v as Float:
			try encodeIfPresent(v, forKey: key)
		case let v as Int:
			try encodeIfPresent(v, forKey: key)
		case let v as Int8:
			try encodeIfPresent(v, forKey: key)
		case let v as Int16:
			try encodeIfPresent(v, forKey: key)
		case let v as Int32:
			try encodeIfPresent(v, forKey: key)
		case let v as Int64:
			try encodeIfPresent(v, forKey: key)
		case let v as UInt:
			try encodeIfPresent(v, forKey: key)
		case let v as UInt8:
			try encodeIfPresent(v, forKey: key)
		case let v as UInt16:
			try encodeIfPresent(v, forKey: key)
		case let v as UInt32:
			try encodeIfPresent(v, forKey: key)
		case let v as UInt64:
			try encodeIfPresent(v, forKey: key)
		default:
			try encodeIfPresent(value, forKey: key)
		}
	}
	
	/// 从指定的key中解码出对象来
	/// 如果T为以下类型:['Bool', 'String', 'Double', 'Float','Int', 'Int8', 'Int16', 'Int32', 'Int64','UInt', 'UInt8', 'UInt16', 'UInt32', 'UInt64'],则会调用具体类型对应的方法,否则调用泛型的T方法
	///
	/// - parameter type: 对象类型
	/// - parameter key: 要解码的key
	/// - returns: 解码出来的对象
	/// - throws: `DecodingError.typeMismatch`: key对应的值,与指定类型不符合
	/// - throws: `CodingError.keyNotFound` : key不存在
	/// - throws: `CodingError.valueNotFound` : key对应的值为null
	public mutating func decodeCodableValue<T>(_ type: T.Type, forKey key: Self.Key) throws -> T where T : Codable {
		switch type {
		case let t as Bool.Type:
			return try decode(t, forKey: key) as! T
		case let t as String.Type:
			return try decode(t, forKey: key) as! T
		case let t as Double.Type:
			return try decode(t, forKey: key) as! T
		case let t as Float.Type:
			return try decode(t, forKey: key) as! T
		case let t as Int.Type:
			return try decode(t, forKey: key) as! T
		case let t as Int8.Type:
			return try decode(t, forKey: key) as! T
		case let t as Int16.Type:
			return try decode(t, forKey: key) as! T
		case let t as Int32.Type:
			return try decode(t, forKey: key) as! T
		case let t as Int64.Type:
			return try decode(t, forKey: key) as! T
		case let t as UInt.Type:
			return try decode(t, forKey: key) as! T
		case let t as UInt8.Type:
			return try decode(t, forKey: key) as! T
		case let t as UInt16.Type:
			return try decode(t, forKey: key) as! T
		case let t as UInt32.Type:
			return try decode(t, forKey: key) as! T
		case let t as UInt64.Type:
			return try decode(t, forKey: key) as! T
		default:
			return try decode(type, forKey: key)
		}
	}
	
	/// 从指定的key中解码出对象来,如果key不存在或者key对应的值为null时,解码出nil
	/// 如果T为以下类型:['Bool', 'String', 'Double', 'Float','Int', 'Int8', 'Int16', 'Int32', 'Int64','UInt', 'UInt8', 'UInt16', 'UInt32', 'UInt64'],则会调用具体类型对应的方法,否则调用泛型的T方法
	///
	/// - parameter type: 对象类型
	/// - parameter key: 要解码的key
	/// - returns: 解码出来的对象或nil(key对应的值为null时)
	/// - throws: `DecodingError.typeMismatch`: key对应的值,与指定类型不符合
	public mutating func decodeCodableValueIfPresent<T>(_ type: T.Type, forKey key: Self.Key) throws -> T? where T : Codable {
		switch type {
		case let t as Bool.Type:
			return try decodeIfPresent(t, forKey: key) as! T?
		case let t as String.Type:
			return try decodeIfPresent(t, forKey: key) as! T?
		case let t as Double.Type:
			return try decodeIfPresent(t, forKey: key) as! T?
		case let t as Float.Type:
			return try decodeIfPresent(t, forKey: key) as! T?
		case let t as Int.Type:
			return try decodeIfPresent(t, forKey: key) as! T?
		case let t as Int8.Type:
			return try decodeIfPresent(t, forKey: key) as! T?
		case let t as Int16.Type:
			return try decodeIfPresent(t, forKey: key) as! T?
		case let t as Int32.Type:
			return try decodeIfPresent(t, forKey: key) as! T?
		case let t as Int64.Type:
			return try decodeIfPresent(t, forKey: key) as! T?
		case let t as UInt.Type:
			return try decodeIfPresent(t, forKey: key) as! T?
		case let t as UInt8.Type:
			return try decodeIfPresent(t, forKey: key) as! T?
		case let t as UInt16.Type:
			return try decodeIfPresent(t, forKey: key) as! T?
		case let t as UInt32.Type:
			return try decodeIfPresent(t, forKey: key) as! T?
		case let t as UInt64.Type:
			return try decodeIfPresent(t, forKey: key) as! T?
		default:
			return try decodeIfPresent(type, forKey: key)
		}
	}
}
